package com.ruoyi.canteen.service.impl;

import java.math.BigDecimal;
import java.util.*;

import com.github.pagehelper.PageHelper;
import com.ruoyi.canteen.constant.CanteenConfig;
import com.ruoyi.canteen.constant.OrderType;
import com.ruoyi.canteen.domain.*;
import com.ruoyi.canteen.mapper.*;
import com.ruoyi.canteen.service.ICanteenMdService;
import com.ruoyi.canteen.utils.BeanCopyUtils;
import com.ruoyi.canteen.vo.CanteenOrderItemVo;
import com.ruoyi.canteen.vo.CanteenOrderVo;
import com.ruoyi.canteen.vo.OrderResultVo;
import com.ruoyi.canteen.vo.OrderShowVo;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.page.PageDomain;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysDictTypeService;
import org.apache.ibatis.annotations.Param;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.ruoyi.canteen.service.ICanteenCpOrderService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import static java.lang.Math.abs;

/**
 * 主订单Service业务层处理
 * 
 * @author zhangw
 * @date 2021-09-19
 */
@Service
public class CanteenCpOrderServiceImpl implements ICanteenCpOrderService 
{
    private static final Logger log = LoggerFactory.getLogger(CanteenCpOrderServiceImpl.class);

    @Autowired
    private CanteenCpOrderMapper canteenCpOrderMapper;

    @Autowired
    private CanteenCpOrderReturnMapper canteenCpOrderReturnMapper;

    @Autowired
    private CanteenCpSpecialMapper canteenCpSpecialMapper;

    @Autowired
    private CanteenCpOrderDetailMapper canteenCpOrderDetailMapper;

    //fwq 0930
    @Autowired
    private CanteenCpOrder1to1Mapper canteenCpOrder1to1Mapper;

    @Autowired
    private CanteenOrderAddressMapper orderAddressMapper;

    @Autowired
    private CanteenQrAddressMapper qrAddressMapper;

    @Autowired
    private CanteenConfig canteenConfig;

    @Autowired
    private ISysDictTypeService dictTypeService;

    /**
     * 查询主订单
     * 
     * @param id 主订单主键
     * @return 主订单
     */
    @Override
    public CanteenCpOrder selectCanteenCpOrderById(Long id)
    {
        return canteenCpOrderMapper.selectCanteenCpOrderById(id);
    }

    /**
     * 查询主订单列表
     * 
     * @param canteenCpOrder 主订单
     * @return 主订单
     */
    @Override
    public List<CanteenCpOrder> selectCanteenCpOrderList(CanteenCpOrder canteenCpOrder)
    {
        return canteenCpOrderMapper.selectCanteenCpOrderList(canteenCpOrder);
    }

    @Override
    public List<CanteenCpOrder> selectCanteenCpOrderList1to1(CanteenCpOrder canteenCpOrder, PageDomain pageDomain) {


        PageHelper.startPage(pageDomain.getPageNum(), pageDomain.getPageSize());

        return canteenCpOrder1to1Mapper.selectCanteenCpOrderList1to1(canteenCpOrder);
    }

    /**
     * 新增主订单
     * 
     * @param canteenCpOrder 主订单
     * @return 结果
     */
    @Override
    public int insertCanteenCpOrder(CanteenCpOrder canteenCpOrder)
    {
        canteenCpOrder.setCreateTime(DateUtils.getNowDate());
        return canteenCpOrderMapper.insertCanteenCpOrder(canteenCpOrder);
    }

    /**
     * 修改主订单
     * 
     * @param canteenCpOrder 主订单
     * @return 结果
     */
    @Override
    public int updateCanteenCpOrder(CanteenCpOrder canteenCpOrder)
    {
        return canteenCpOrderMapper.updateCanteenCpOrder(canteenCpOrder);
    }

    /**
     * 批量删除主订单
     * 
     * @param ids 需要删除的主订单主键
     * @return 结果
     */
    @Override
    public int deleteCanteenCpOrderByIds(Long[] ids)
    {
        return canteenCpOrderMapper.deleteCanteenCpOrderByIds(ids);
    }

    /**
     * 删除主订单信息
     * 
     * @param id 主订单主键
     * @return 结果
     */
    @Override
    public int deleteCanteenCpOrderById(Long id)
    {
        return canteenCpOrderMapper.deleteCanteenCpOrderById(id);
    }

    /**
     * 新增主订单+订单明细
     * @param canteenOrderVo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public CanteenCpOrder newCanteenCpOrder(CanteenOrderVo canteenOrderVo){
        int result = 0;
        CanteenCpOrder mainOrder = new CanteenCpOrder();
        List<SysDictData> buildDict = dictTypeService.selectDictDataByType("location_building");
        try{
            BeanCopyUtils.copyProperties(canteenOrderVo, mainOrder);
            String orderNo = this.generateOrderSn(canteenOrderVo.getMdId().toString(), canteenOrderVo.getUserId());
            mainOrder.setOrderNo(orderNo);
            mainOrder.setCreateTime(new Date());
            if(canteenOrderVo.getOrderType().equals(OrderType.ORDER_TYPE_NORMAL.toString())){
                // 在线点餐地址
                // 增加当前配送信息至订单表
                CanteenOrderAddress curAddress = orderAddressMapper.selectCanteenOrderAddressById(mainOrder.getAddressId());
                mainOrder.setDeliverLinkMan(curAddress.getLinkMan());
                mainOrder.setPhone(curAddress.getPhone());
                // 组装-配送地址
                String deliveryAddress = curAddress.getAddress();
                if(StringUtils.isNotEmpty(curAddress.getBuildingAddress())) {
                    for(SysDictData dictData : buildDict){
                        if(dictData.getDictValue().equals(curAddress.getBuildingAddress())){
                            deliveryAddress = dictData.getDictLabel() + curAddress.getAddress();
                        }
                    }
                }
                mainOrder.setAddress(deliveryAddress);
            }else if(canteenOrderVo.getOrderType().equals(OrderType.ORDER_TYPE_HALL.toString())){
                // 现场点餐地址
                CanteenQrAddress curAddress = qrAddressMapper.selectCanteenQrAddressById(canteenOrderVo.getAddressId());
                if(curAddress != null){
                    String deliveryAddress = curAddress.getAddress();
                    mainOrder.setAddress(deliveryAddress);
                }
            }
            result = canteenCpOrderMapper.insertCanteenCpOrder(mainOrder);
            Long orderId = mainOrder.getId();
            // 再插订单明细表
            List<CanteenOrderItemVo> items = canteenOrderVo.getItems();
//            double totalPrice = 0;
            BigDecimal totalPrice = new BigDecimal("0");
            for(CanteenOrderItemVo itemVo : items){
                if(itemVo.getNumber() > 0 && itemVo.getPrice() >= 0){
                    // TODO 目前id 暂时为菜品id
                    itemVo.setCpId(itemVo.getId().intValue());
                    itemVo.setId(null);
                    List<CanteenCpSpecial> canteenCpSpecialList =
                            canteenCpSpecialMapper.selectCanteenCpSpecialByCpId(itemVo.getCpId());
                    if(canteenCpSpecialList.size() > 0){
                        CanteenCpSpecial canteenCpSpecial = canteenCpSpecialList.get(0);
                        CanteenCpOrderDetail detail = new CanteenCpOrderDetail();
                        detail.setOrderId(orderId);
                        detail.setOrderNo(orderNo);
                        detail.setMdId(mainOrder.getMdId());
                        detail.setCpId(Long.valueOf(itemVo.getCpId()));
                        detail.setAmount(itemVo.getNumber());
//                        detail.setPrice(canteenCpSpecial.getPrice().doubleValue());
//                        detail.setCpSum(detail.getPrice() * detail.getAmount());
                        detail.setPrice(canteenCpSpecial.getPrice());
                        BigDecimal b_amount = new BigDecimal (itemVo.getNumber().toString ());
                        detail.setCpSum(detail.getPrice().multiply(b_amount));
                        result = canteenCpOrderDetailMapper.insertCanteenCpOrderDetail(detail);
                        // TODO 更新菜品对应库存表
//                        if(Optional.ofNullable(canteenCpSpecial.getStorageModel()).orElse(-1) == 1){
//                            int sotckResult =
//                                    canteenCpSpecialMapper.reduceCpSpecialStock(canteenCpSpecial.getId(), detail.getAmount());
//                            if(sotckResult < 1){
//                                throw new ServiceException("库存不足");
//                            }
//                        }
//                        totalPrice = totalPrice + detail.getCpSum();
                        totalPrice = totalPrice.add(detail.getCpSum());
                    }
                }
            }
//            if(totalPrice != mainOrder.getTotalPrice()){
//                result = 0;
//                log.error("新增订单时，订单总金额不一致！mainOrder：" + mainOrder.toString() + ";totalPrice:" + String.valueOf(totalPrice));
//                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//            }
//            if (! isEqual(totalPrice, mainOrder.getTotalPrice())) {
            if (!(totalPrice.compareTo(mainOrder.getTotalPrice())==0)) {
                result = 0;
                log.error("新增订单时，订单总金额不一致！mainOrder：" + mainOrder.toString() + ";" +
                        "totalPrice:" + String.valueOf(totalPrice));
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return null;
            }
        }catch (Exception ex){
            result = 0;
            log.error("新增订单出错："+ ex.toString());
            //@Transactional和try catch捕获异常会让注解失效
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new ServiceException("订单出错:"+ex.getMessage());
        }
        return mainOrder;
    }

    private boolean isEqual(double a, double b){
        return abs(a-b) < 0.00001;
    }

    @Override
    public OrderResultVo convertCpOrderToVo(CanteenCpOrder mainOrder){
        OrderResultVo vo = new OrderResultVo();
        vo.setId(mainOrder.getId());
        vo.setMdId(mainOrder.getMdId());
        vo.setOrderNo(mainOrder.getOrderNo());
        BigDecimal cs = new BigDecimal("100");
//        vo.setTotalPrice(new Double(mainOrder.getTotalPrice() * 100).intValue());
        vo.setTotalPrice(mainOrder.getTotalPrice().multiply(cs).intValue());
        String subMchId = canteenConfig.getMdAccount().get(mainOrder.getMdId().intValue()).toString();
        vo.setSubMchId(subMchId);
        return vo;
    }

    /**
     * 生成订单编号
     * @param mdId
     * @param userId
     * @return
     */
    public String generateOrderSn(String mdId, Long userId){
        String curTime = DateUtils.dateTimeNow();
        Random rand = new Random(System.currentTimeMillis());
        Integer random = rand.nextInt(10000);
        String userString = String.format("%06d",userId+99);
        return curTime + random.toString() + userString + mdId;
    }

    /**
     * 查询当前用户的订单列表
     * @param userId 当前用户
     * @return
     */
    @Override
    public List<OrderShowVo> selectOrderShowVoList(Long userId,String payFlag){
        return canteenCpOrderMapper.selectOrderShowVoList(userId, payFlag);
    }

    /**
     * 查询当前用户的主订单
     * @param userId
     * @param orderId
     * @return
     */
    @Override
    public OrderShowVo selectOrderShowVo(Long userId, Long orderId){
        return canteenCpOrderMapper.selectOrderShowVo(userId, orderId);
    }

    /**
     * 根据ID查询当前主订单(包含商户号)
     * @param orderId
     * @return
     */
    @Override
    public OrderShowVo selectOrderShowByOrderId(Long orderId){
        return canteenCpOrderMapper.selectOrderShowByOrderId(orderId);
    }

    @Override
    public int confirmPayById(Long userId, Long orderId){
        return canteenCpOrderMapper.confirmPayById(userId, orderId);
    }

    @Override
    public int confirmPayByNo(Long userId,String orderNo){
        return canteenCpOrderMapper.confirmPayByNo(userId, orderNo);
    }

    @Override
    public int confirmPayByOpenId(String openid, String orderNo, String serialNo){
        return canteenCpOrderMapper.confirmPayByOpenId(openid, orderNo, serialNo);
    }

    /**
     * 根据用户openid + 订单NO 更新订单支付状态
     * @param userCode
     * @param orderNo
     * @return
     */
    @Override
    public int confirmPayByUserCodeAndNo(String userCode, String orderNo){
        int count = 0;
        try{
            count = canteenCpOrderMapper.confirmPayByUserCodeAndNo(userCode, orderNo);
        }catch (Exception ex){
            log.error("订单号："+ orderNo + "更新订单支付状态失败", ex);
        }
        return count;
    }

    /**
     * 查询当前用户的订单列表(payFlag = 1 已付款订单)
     * @param userId 当前用户
     * @param payFlag 付款状态
     * @param day 最近几天
     * @return
     */
    @Override
    public List<OrderShowVo> selectDefaultOrderShowVoList(Long userId, String payFlag,  Integer day){
        return canteenCpOrderMapper.selectDefaultOrderShowVoList(userId, payFlag, day);
    }

    /**
     * 根据订单编号查询主订单详情
     * @param orderNo 订单编号
     * @return
     */
    @Override
    public CanteenCpOrder selectCpOrderByNo(String orderNo){

        return canteenCpOrderMapper.selectCpOrderByNo(orderNo);
    }

    /**
     * 用户发起售后-退货申请
     * order_status=6
     * @param userId userId
     * @param orderId 订单id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int canncelOrderById(Long userId, Long orderId, Integer reasonId, Integer mdId) {
        int result = 0;
        // 1、变更订单为退货中（退货申请）状态
        // 验证只能本人发起本人的退款申请
        result = canteenCpOrderMapper.canncelOrderById(userId, orderId);
        if(result > 0){
            //  2、写入订单退货表
            CanteenCpOrderReturn returnOrder = new CanteenCpOrderReturn();
            returnOrder.setOrderId(orderId);
            returnOrder.setMdId(mdId);
            returnOrder.setReturnReason(reasonId);
            returnOrder.setReturnApplyStatus(OrderType.ORDER_RETURN_DSH);
            returnOrder.setApplyTime(new Date());
            returnOrder.setUpdateBy(userId.toString());
            returnOrder.setUpdateTime(new Date());
            canteenCpOrderReturnMapper.insertCanteenCpOrderReturn(returnOrder);
        }
        return result;
    }

//    /**
//     * TODO 拒绝-取消订单
//     * order_status=7：交易关闭（退货审核不通过）11：售后中（退货已入库）
//     * order_status=12：交易关闭（完成退款）
//     * @param orderId 订单id
//     * @param orderStatus  订单状态
//     * @return
//     */
//    @Override
//    @Transactional(rollbackFor = Exception.class)
//    public int rejectOrderCancelById(Long userId, Integer orderStatus, Long orderId) {
//        int result = 0;
//        // 1. 更新订单状态为：order_status=7：交易关闭（退货审核不通过）
//        result = canteenCpOrderMapper.updateOrderStatusById(7, orderId);
//        // 2. 更新订单退货表
//        if(result > 0){
//            CanteenCpOrderReturn canteenCpOrderReturn = new CanteenCpOrderReturn();
//            canteenCpOrderReturn.setOrderId(orderId);
//            canteenCpOrderReturn.setReturnApplyStatus(OrderType.ORDER_RETURN_SHBTG);
//            canteenCpOrderReturn.setReturnCheckerId(userId);
//            canteenCpOrderReturn.setCheckTime(new Date());
//            canteenCpOrderReturn.setUpdateBy(userId.toString());
//            canteenCpOrderReturn.setUpdateTime(new Date());
//            canteenCpOrderReturnMapper.updateReturnOrder(canteenCpOrderReturn);
//        }
//        return result;
//    }
//
//    /**
//     * TODO 批准同意-取消订单
//     * order_status=7：交易关闭（退货审核不通过）11：售后中（退货已入库）
//     * order_status=12：交易关闭（完成退款）
//     * @param orderId 订单id
//     * @param orderStatus  订单状态
//     * @return
//     */
//    @Override
//    @Transactional(rollbackFor = Exception.class)
//    public int approvedOrderCancelById(Long userId, Integer orderStatus, Long orderId) {
//        int result = 0;
//        // 1. 更新订单状态为：order_status=12：交易关闭（完成退款）
//        result = canteenCpOrderMapper.updateOrderStatusById(12, orderId);
//
//        if(result > 0){
//            // 2. 根据订单类型，调用退款接口
//
//            // 3. 更新订单退货表
//            CanteenCpOrderReturn canteenCpOrderReturn = new CanteenCpOrderReturn();
//            canteenCpOrderReturn.setOrderId(orderId);
//            canteenCpOrderReturn.setReturnApplyStatus(OrderType.ORDER_RETURN_SHTG);
//            canteenCpOrderReturn.setReturnCheckerId(userId);
//            canteenCpOrderReturn.setCheckTime(new Date());
//            canteenCpOrderReturn.setUpdateBy(userId.toString());
//            canteenCpOrderReturn.setUpdateTime(new Date());
//            canteenCpOrderReturnMapper.updateReturnOrder(canteenCpOrderReturn);
//
//        }
//        return result;
//    }

}